/*
 * GSqliteConnectionPool.cpp
 *
 *  Created on: 2010-12-22
 *      Author: minhua
 */

#include "GSqliteConnectionPool.h"

GSqliteConnectionPool::GSqliteConnectionPool(QString filename, int maxReadConnectionCount)
{
	_filename = filename;
	_writeConnectionName = "write";
	_readConnectionIndex = 0;
	_maxReadConnectionCount = maxReadConnectionCount;
}

GSqliteConnectionPool::~GSqliteConnectionPool()
{
	_writeMutex.lock();
	QSqlDatabase::database(_writeConnectionName).close();
	QSqlDatabase::removeDatabase(_writeConnectionName);
	_writeMutex.unlock();

	_readMutex.lock();
	for(int i=1; i<=_idleReadConnectionNameList.count(); i++)
	{
		QString connectionName = _idleReadConnectionNameList.at(i-1);
		QSqlDatabase::database(connectionName).close();
		QSqlDatabase::removeDatabase(connectionName);
	}
	_idleReadConnectionNameList.clear();
	for(int i=1; i<=_busyReadConnectionNameList.count(); i++)
	{
		QString connectionName = _busyReadConnectionNameList.at(i-1);
		QSqlDatabase::database(connectionName).close();
		QSqlDatabase::removeDatabase(connectionName);
	}
	_busyReadConnectionNameList.clear();
	_readMutex.unlock();
}

QSqlDatabase GSqliteConnectionPool::getReadConnection()
{
	_readMutex.lock();

	QString connectionName;
	if(_idleReadConnectionNameList.isEmpty())
	{
		connectionName = "read_";
		connectionName.append(QString::number(_readConnectionIndex));
		QSqlDatabase connection = QSqlDatabase::addDatabase("QSQLITE", connectionName);
		connection.setDatabaseName(_filename);
		_readConnectionIndex++;
		if(!connection.open())
		{
			qFatal("GSqliteConnectionPool.getReadConnection: Open database failed.");
		}
	}
	else
	{
		connectionName = _idleReadConnectionNameList.first();
		_idleReadConnectionNameList.pop_front();
		_busyReadConnectionNameList.push_back(connectionName);
	}

	_readMutex.unlock();

	return QSqlDatabase::database(connectionName);
}

QSqlDatabase GSqliteConnectionPool::getWriteConnection()
{
	_writeMutex.lock();

	if(!QSqlDatabase::contains(_writeConnectionName))
	{
		QSqlDatabase connection = QSqlDatabase::addDatabase("QSQLITE", _writeConnectionName);
		connection.setDatabaseName(_filename);
		if(!connection.open())
		{
			qFatal("GSqliteConnectionPool.getWriteConnection: Open database failed.");
		}
	}

	return QSqlDatabase::database(_writeConnectionName);
}

void GSqliteConnectionPool::releaseConnection(QSqlDatabase connection)
{
	if(connection.connectionName()==_writeConnectionName)
	{
		_writeMutex.unlock();
	}
	else
	{
		_readMutex.lock();

		_busyReadConnectionNameList.removeOne(connection.connectionName());
		if((_busyReadConnectionNameList.count()+_idleReadConnectionNameList.count())>=_maxReadConnectionCount)
		{
			connection.close();
			QSqlDatabase::removeDatabase(connection.connectionName());
		}
		else
		{
			_idleReadConnectionNameList.push_back(connection.connectionName());
		}

		_readMutex.unlock();
	}
}
